package fr.sedoo.commons.metadata.utils.pdf;

import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.commons.lang.StringUtils;
import org.geotoolkit.gml.xml.v311.TimeIndeterminateValueType;
import org.geotoolkit.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.opengis.metadata.distribution.Format;
import org.opengis.metadata.extent.GeographicBoundingBox;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.Image;
import com.lowagie.text.ListItem;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

import fr.sedoo.commons.metadata.utils.LabelProvider;
import fr.sedoo.commons.metadata.utils.domain.Contact;
import fr.sedoo.commons.metadata.utils.domain.DescribedURL;
import fr.sedoo.commons.metadata.utils.domain.RBVMetadata;
import fr.sedoo.commons.metadata.utils.pdf.labelprovider.LanguageLabelProvider;
import fr.sedoo.commons.metadata.utils.pdf.labelprovider.RoleLabelProvider;
import fr.sedoo.commons.metadata.utils.pdf.labelprovider.StatusLabelProvider;
import fr.sedoo.commons.metadata.utils.pdf.labelprovider.UpdateRythmLabelProvider;

public class PrintService
{

	public final static String RBV_PREFIX = "rbvPrint";

	public PrintService()
	{
		this(null);
	}

	private Locale locale = Locale.ENGLISH;

	public PrintService(Locale locale)
	{
		if (locale != null)
		{
			this.locale = locale;
		} else
		{
			this.locale = Locale.ENGLISH;
		}
		labelProvider = new LabelProvider(this.locale);
		statusLabelProvider = new StatusLabelProvider(this.locale);
		resourceUpdateRythmLabelProvider = new UpdateRythmLabelProvider(this.locale);
		roleLabelProvider = new RoleLabelProvider(this.locale);

	}

	private PdfEventListener eventListener;
	private RBVMetadata metadata;
	private String outputFileName;
	private String currentElement = "";
	private final LabelProvider labelProvider;
	private final StatusLabelProvider statusLabelProvider;
	private final RoleLabelProvider roleLabelProvider;
	private final UpdateRythmLabelProvider resourceUpdateRythmLabelProvider;
	private static Font h2Font = FontFactory.getFont(FontFactory.HELVETICA, 15, Font.NORMAL);
	private static Font titleFont = FontFactory.getFont(FontFactory.HELVETICA, 15, Font.NORMAL);
	private static Font normalFont = FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL);
	private static Color backgroundColor = new Color(0xE8E8E8);

	static
	{
		h2Font.setColor(new Color(0x4A99C6));
	}

	public File metadataToPdf(RBVMetadata metadata) throws Exception
	{
		this.metadata = metadata;
		Document document = null;
		File output = null;
		if (outputFileName == null)
		{
			output = File.createTempFile(RBV_PREFIX, ".pdf");
		} else
		{
			output = new File(outputFileName);
		}
		try
		{
			document = openDocument(output);
			writeFirstPage(document);
			document.newPage();
			writeIdentificationPart(document);
			document.newPage();
			writeContactPart(document);
			document.newPage();
			writeKeywordPart(document);
			document.newPage();
			writeLocationPart(document);
			document.newPage();
			writeTemporalExtentPart(document);
			document.newPage();
			writeConstraintPart(document);
			document.newPage();
			writeOtherPart(document);
			return output;
		} catch (Exception e)
		{
			throw e;
		} finally
		{
			closeDocument(document);
		}
	}

	private Document openDocument(File output) throws Exception
	{
		Document document = new Document(PageSize.A4);
		PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(output));
		eventListener = new PdfEventListener(this, metadata);
		writer.setPageEvent(eventListener);
		document.open();
		return document;
	}

	private void writeFirstPage(Document document) throws DocumentException
	{
		PdfPTable contentTable = new PdfPTable(1);
		PdfPTable table = new PdfPTable(1);

		//table.addCell(getFirstPageCell(metadata.getResourceTitleDisplay(locale), titleFont));

//		table.addCell(getFirstPageCell(ensureColumn(getLabel("commons.observatory")) + " " + StringUtils.trimToEmpty(metadata.getObservatoryName()), normalFont));
//		table.addCell(getFirstPageCell(ensureColumn(getLabel("commons.drainageBasin")) + " " + StringUtils.trimToEmpty(metadata.getDrainageBasinName()), normalFont));
		table.setWidthPercentage(100);

		PdfPCell contentCell = new PdfPCell();
		contentCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
		contentCell.setHorizontalAlignment(Element.ALIGN_RIGHT);

		Image logo;
		try
		{
			logo = Image.getInstance(this.getClass().getResource("rbv.png"));
			logo.scaleAbsolute(200, 100);

		} catch (Exception e)
		{
			throw new DocumentException(e.getMessage());
		}

		PdfPCell headerCell = new PdfPCell(logo, false);
		headerCell.setBorder(0);
		headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);

		contentCell.setVerticalAlignment(Element.ALIGN_BOTTOM);
		contentCell.setHorizontalAlignment(Element.ALIGN_RIGHT);

		// cell.setHorizontalAlignment(Element.ALIGN_CENTER);
		// cell.setVerticalAlignment(Element.ALIGN_TOP);

		contentCell.addElement(table);
		contentCell.setPaddingBottom(7);
		contentCell.setBorder(0);

		contentTable.addCell(headerCell);
		contentTable.addCell(contentCell);
		contentTable.setWidthPercentage(100);
		contentTable.setExtendLastRow(true);

		document.add(contentTable);
	}

	private PdfPCell getFirstPageCell(String label, Font font)
	{
		PdfPCell cell = new PdfPCell(new Phrase(label, font));
		cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
		cell.setVerticalAlignment(Element.ALIGN_CENTER);
		cell.setBackgroundColor(backgroundColor);
		cell.setBorder(0);
		cell.setPaddingBottom(7);
		cell.setPaddingRight(7);

		return cell;
	}

	private void writeIdentificationPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.identificationTabHeader"), document);
		writeSection(getLabel("metadataEditing.generalInformations"), document);
		//writePairValue(getLabel("metadataEditing.resourceTitle"), metadata.getResourceTitleDisplay(locale), document);
		writePairValue(getLabel("metadataEditing.resourceAlternateTitle"), metadata.getResourceAlternateTitle(), document);
		//writePairValue(getLabel("metadataEditing.resourceAbstract"), metadata.getResourceAbstractDisplay(locale), document);
		
		//TOD: Identifiants
		writePairValue(getLabel("metadataEditing.resourceStatus"), statusLabelProvider.getLabel(metadata.getStatus()), document);
		
		writeSection(getLabel("metadataEditing.links"), document);
		
		//writeDescribedURLList(getLabel("metadataEditing.resourceURL"), metadata.getResourceURL(), document);
		writeDescribedURLList(getLabel("metadataEditing.SnapshotList"), metadata.getSnapshotURL(), document);
	}
	
	private void writeContactPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.contactTabHeader"), document);
		
		writeSection(getLabel("metadataEditing.principalInvestigators"), document);
		writeContactListWithoutRoles(metadata.getPIContacts(), document);
		writeSection(getLabel("metadataEditing.dataPointsOfContact"), document);
		writeContactListWithoutRoles(metadata.getDataContacts(), document);
		writeSection(getLabel("metadataEditing.owners"), document);
		writeContactListWithoutRoles(metadata.getOwnerContacts(), document);
		writeSection(getLabel("metadataEditing.metadataPointsOfContact"), document);
		writeContactListWithoutRoles(metadata.getMetadataContacts(), document);
		writeSection(getLabel("metadataEditing.otherRoles"), document);
		writeContactListWithoutRoles(metadata.getOtherContacts(), document);
	}
	
	private void writeKeywordPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.keywordTabHeader"), document);
	}

	private void writeDescribedURLList(String label, List<DescribedURL> urls, Document document) throws DocumentException
	{
		if (isEmpty(urls))
		{
			PdfPTable table = getDefaultTable();
			writeEmptyTable(label, table);
			document.add(table);
		} else
		{
			writePairValue(label, getValueFromDescribedURLList(urls), document);
		}
	}

	private com.lowagie.text.List getValueFromDescribedURLList(List<DescribedURL> urls)
	{
		StringBuilder sb = new StringBuilder();
		com.lowagie.text.List list = new com.lowagie.text.List(com.lowagie.text.List.UNORDERED);
		list.setListSymbol("\u2022");
		Iterator<DescribedURL> iterator = urls.iterator();
		while (iterator.hasNext())
		{
			DescribedURL describedURL = iterator.next();
			list.add(new ListItem(" " + renderDescribedURL(describedURL), normalFont));
		}
		return list;
	}

	private com.lowagie.text.List getValueFromStringList(List<String> urls)
	{
		StringBuilder sb = new StringBuilder();
		com.lowagie.text.List list = new com.lowagie.text.List(com.lowagie.text.List.UNORDERED);
		list.setListSymbol("\u2022");
		Iterator<String> iterator = urls.iterator();
		while (iterator.hasNext())
		{
			list.add(new ListItem(" " + iterator.next(), normalFont));
		}
		return list;
	}

	public String renderDescribedURL(DescribedURL describedURL)
	{
		if (StringUtils.isEmpty(describedURL.getLabel()))
		{
			return describedURL.getLink();
		} else
		{
			return describedURL.getLabel() + " (" + describedURL.getLink() + ")";
		}
	}

	private void writeEmptyTable(String label, PdfPTable table)
	{
		table.addCell(getLabelCell(label));
		table.addCell(getEmptyCell(getLabel("commons.emptyList")));
	}
	
	private void writeEmptyTableWithoutLabel(PdfPTable table)
	{
		PdfPCell emptyCell = getEmptyCell(" "+getLabel("commons.emptyList"));
		emptyCell.setColspan(2);
		table.addCell(emptyCell);
	}

	private void writeContactListWithoutRoles(List<Contact> resourceContacts, Document document) throws DocumentException
	{

		PdfPTable table = null;
		if (isEmpty(resourceContacts))
		{
			table = getDefaultTable();
			writeEmptyTableWithoutLabel(table);

		} else
		{
			table = getDefaultTable();
			addContactListCell("", resourceContacts, table, false, document);
		}
		document.add(table);

	}
	
	private void addContactListCell(String label, List<Contact> resourceContacts, PdfPTable table, Boolean displayRoles, Document document)
	{
		PdfPTable nestedTable;
		if (displayRoles)
		{
			nestedTable = new PdfPTable(5);
		}
		else
		{
			nestedTable = new PdfPTable(4);
		}
		nestedTable.addCell(getHeaderCell(getLabel("person.personName")));
		nestedTable.addCell(getHeaderCell(getLabel("person.email")));
		nestedTable.addCell(getHeaderCell(getLabel("person.organisationName")));
		nestedTable.addCell(getHeaderCell(getLabel("person.address")));
		if (displayRoles)
		{
			nestedTable.addCell(getHeaderCell(getLabel("person.roles")));
		}

		Iterator<Contact> iterator = resourceContacts.iterator();
		while (iterator.hasNext())
		{
			Contact contact = iterator.next();
			nestedTable.addCell(getTableCell(contact.getIndividualName()));
			nestedTable.addCell(getTableCell(contact.getEmailAddress()));
			nestedTable.addCell(getTableCell(contact.getOrganisationName()));
			nestedTable.addCell(getTableCell(contact.getCompleteAddress().replace('|', '\n')));
			if (displayRoles)
			{
				nestedTable.addCell(getTableCell(roleLabelProvider.getLabel(contact.getRole())));
			}
		}

		nestedTable.setWidthPercentage(100);
		PdfPCell aux = getEmptyCell("");
		aux.setColspan(2);
		aux.setHorizontalAlignment(Element.ALIGN_CENTER);
		aux.addElement(nestedTable);
		table.addCell(aux);
		table.setWidthPercentage(100);

	}

	private void writeLocationPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.geographicalLocationTabHeader"), document);

		writePairValue(getLabel("commons.observatory"), "", document);
		writePairValue(getLabel("commons.drainageBasin"), "", document);
		writePairValue(getLabel("drainageBasinEditingView.siteName"),"", document);

		writeSection(getLabel("metadataEditing.location"), document);
		
		GeographicBoundingBox geographicBoundingBox = metadata.getGeographicBoundingBoxes().get(0);

		String eastBoundLongitudeDisplay = "";
		String westBoundLongitudeDisplay = "";
		String northBoundLatitudeDisplay = "";
		String southBoundLatitudeDisplay = "";

		if (geographicBoundingBox != null)
		{
			eastBoundLongitudeDisplay = protectDouble(geographicBoundingBox.getEastBoundLongitude());
			northBoundLatitudeDisplay = protectDouble(geographicBoundingBox.getNorthBoundLatitude());
			westBoundLongitudeDisplay = protectDouble(geographicBoundingBox.getWestBoundLongitude());
			southBoundLatitudeDisplay = protectDouble(geographicBoundingBox.getSouthBoundLatitude());
		}

		writePairValue(getLabel("mapSelector.eastLongitude"), eastBoundLongitudeDisplay, document);
		writePairValue(getLabel("mapSelector.northLatitude"), northBoundLatitudeDisplay, document);
		writePairValue(getLabel("mapSelector.westLongitude"), westBoundLongitudeDisplay, document);
		writePairValue(getLabel("mapSelector.southLatitude"), southBoundLatitudeDisplay, document);

		if ((eastBoundLongitudeDisplay.length() > 0) && (westBoundLongitudeDisplay.length() > 0) && ((northBoundLatitudeDisplay.length() > 0)) && (southBoundLatitudeDisplay.length() > 0))
		{
			writeLocationImage(document);
		}
	}

	private void writeLocationImage(Document document) throws DocumentException
	{
		try
		{
			PdfPTable oneCellTable = getOneCellTable();
			String imageUrl = getImageUrlFromBoundingBox(metadata.getGeographicBoundingBoxes().get(0));
			Image map = Image.getInstance(new URL(imageUrl));
			PdfPCell cell = new PdfPCell(map, false);
			cell.setHorizontalAlignment(Element.ALIGN_CENTER);
			cell.setVerticalAlignment(Element.ALIGN_TOP);
			cell.setBackgroundColor(backgroundColor);
			cell.setBorder(0);
			cell.setBorderWidthBottom(2);
			cell.setBorderColorBottom(Color.WHITE);
			cell.setPaddingBottom(7);
			cell.setPaddingTop(7);
			oneCellTable.addCell(cell);
			document.add(oneCellTable);
		} catch (Exception e)
		{
			throw new DocumentException(e.getMessage());
		}

	}

	private String getImageUrlFromBoundingBox(GeographicBoundingBox geographicBoundingBox)
	{
		StringBuilder sb = new StringBuilder();
		if ((geographicBoundingBox.getEastBoundLongitude() == geographicBoundingBox.getWestBoundLongitude())
				&& (geographicBoundingBox.getNorthBoundLatitude() == geographicBoundingBox.getSouthBoundLatitude()))
		{
			sb.append("https://maps.googleapis.com/maps/api/staticmap?sensor=false&size=400x400&maptype=hybrid&markers=color:blue%7C");
			sb.append(geographicBoundingBox.getSouthBoundLatitude() + "," + geographicBoundingBox.getEastBoundLongitude());
			sb.append("&center=" + geographicBoundingBox.getSouthBoundLatitude() + "," + geographicBoundingBox.getEastBoundLongitude());
		} else
		{
			sb.append("https://maps.googleapis.com/maps/api/staticmap?sensor=false&size=400x400&maptype=hybrid&path=color:0xE85F0Eaa%7Cweight:2%7Cfillcolor:0xE85F0E33%7C");
			sb.append("" + geographicBoundingBox.getNorthBoundLatitude() + "," + geographicBoundingBox.getEastBoundLongitude() + "%7C");
			sb.append("" + geographicBoundingBox.getNorthBoundLatitude() + "," + geographicBoundingBox.getWestBoundLongitude() + "%7C");
			sb.append("" + geographicBoundingBox.getSouthBoundLatitude() + "," + geographicBoundingBox.getWestBoundLongitude() + "%7C");
			sb.append("" + geographicBoundingBox.getSouthBoundLatitude() + "," + geographicBoundingBox.getEastBoundLongitude() + "%7C");
			sb.append("" + geographicBoundingBox.getNorthBoundLatitude() + "," + geographicBoundingBox.getEastBoundLongitude());
		}
		return sb.toString();
	}

	private String protectDouble(Double value)
	{
		if (value == null)
		{
			return "";
		}
		if (value.isNaN())
		{
			return "";
		} else
			return value.toString();
	}

	private void writeTemporalExtentPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.temporalExtentHeader"), document);
		
		writeSection(getLabel("metadataEditing.coveredPeriods"), document);
		
		
		writePairValue(getLabel("metadataEditing.startDate"), metadata.getResourceBeginDate(), document);
		String endDate = metadata.getResourceEndDate();
		if (endDate != null)
		{
			if (metadata.getResourceEndDate().compareToIgnoreCase(TimeIndeterminateValueType.NOW.name()) == 0)
			{
				endDate = getLabel("now");
			}
		}
		writePairValue(getLabel("metadataEditing.endDate"), endDate, document);
		
		writeSection(getLabel("metadataEditing.temporalMilestones"), document);
		writePairValue(getLabel("metadataEditing.creationDate"), metadata.getCreationDate(), document);
		writePairValue(getLabel("metadataEditing.lastRevisionDate"), metadata.getLastRevisionDate(), document);
		writePairValue(getLabel("metadataEditing.publicationDate"), metadata.getPublicationDate(), document);
		
		writeSection(getLabel("metadataEditing.maintenance"), document);
		writePairValue(getLabel("metadataEditing.resourceUpdateRythm"), resourceUpdateRythmLabelProvider.getLabel(metadata.getResourceUpdateRythm()), document);
		
		
	}

	private void writeConstraintPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.constraintTabHeader"), document);
//		writePairValue(getLabel("metadataEditing.useConditions"), metadata.getUseConditions(), document);
//		writePairValue(getLabel("metadataEditing.publicAccessLimitations"), metadata.getPublicAccessLimitations(), document);
	}

	private void writeOtherPart(Document document) throws DocumentException
	{
		writeHeader(getLabel("metadataEditing.otherTabHeader"), document);
		writeSection(getLabel("metadataEditing.technicalInformations"), document);
		
		String aux = "";
		Format resourceFormat = metadata.getResourceFormat();
		if (resourceFormat != null)
		{
			aux = resourceFormat.getName().toString();
			if (resourceFormat.getVersion() != null)
			{
				String version = resourceFormat.getVersion().toString();
				if (version != null)
				{
					aux = aux + " (" + version + ")";
				}
			}
		}
		writePairValue(getLabel("metadataEditing.resourceFormat"), aux, document);
		writePairValue(getLabel("metadataEditing.charset"), metadata.getResourceEncodingCharset(), document);
		writePairValue(getLabel("metadataEditing.coordinateSystem"), metadata.getCoordinateSystem(), document);
		
		writeSection(getLabel("metadataEditing.languages"), document);

		List<String> resourceLanguagesCode = metadata.getResourceLanguages();

		// Conversion des codes en noms affichables
		List<String> resourceLanguageDisplay = new ArrayList<String>();
		if (resourceLanguagesCode != null)
		{
			Iterator<String> iterator = resourceLanguagesCode.iterator();
			while (iterator.hasNext())
			{
				resourceLanguageDisplay.add(LanguageLabelProvider.getLanguageFromCode(iterator.next(), locale));
			}
		}

		writeResourceLanguagesList(getLabel("metadataEditing.dataLanguages"), resourceLanguageDisplay, document);
		
		String metadataLanguage = metadata.getMetadataLanguage();
		if (metadataLanguage == null)
		{
			metadataLanguage = "";
		} else
		{
			metadataLanguage = LanguageLabelProvider.getLanguageFromCode(metadataLanguage, locale);
		}
		
		writePairValue(getLabel("metadataEditing.metadataLanguage"), metadataLanguage, document);
		
		writeSection(getLabel("metadataEditing.metadataTabHeader"), document);
		writePairValue(getLabel("metadataEditing.metatadataUuid"), metadata.getUuid(), document);

		writePairValue(getLabel("metadataEditing.lastModificationDate"), metadata.getMetadataDate(), document);
	}

	private void writeResourceLanguagesList(String label, List<String> resourceLanguages, Document document) throws DocumentException
	{

		if (isEmpty(resourceLanguages))
		{
			PdfPTable table = getDefaultTable();
			writeEmptyTable(label, table);
			document.add(table);
		} else
		{
			writePairValue(label, getValueFromStringList(resourceLanguages), document);
		}

	}

	private void writeSection(String sectionName, Document document) throws DocumentException
	{
		setCurrentElement(sectionName);
		PdfPTable table = new PdfPTable(1);
		PdfPCell cellule = new PdfPCell(new Phrase(sectionName, h2Font));
		cellule.setBorder(0);
		cellule.setPaddingBottom(5);
		table.addCell(cellule);
		table.setWidthPercentage(100);
		document.add(table);
	}
	
	private void writeHeader(String sectionName, Document document) throws DocumentException
	{
		setCurrentElement(sectionName);
		eventListener.writeBookMark(sectionName);
		PdfPTable table = new PdfPTable(1);
		PdfPCell cellule = new PdfPCell(new Phrase(sectionName, h2Font));
		cellule.setBorder(0);
		cellule.setBorderWidthBottom(1);
		cellule.setBorderColorBottom(new Color(0x4A99C6));
		cellule.setPaddingBottom(5);
		table.addCell(cellule);
		table.setWidthPercentage(100);
		document.add(table);
		writeNewLine(document);
	}

	private void writeNewLine(Document document) throws DocumentException {
		PdfPTable fakeTable = new PdfPTable(1);
		
		PdfPCell cell = new PdfPCell(new Phrase(" "));
		cell.setBorder(0);
		fakeTable.addCell(cell);
		document.add(fakeTable);
		
	}

	private void writePairValue(String label, String value, Document document) throws DocumentException
	{
		String aux = value;
		if (aux == null)
		{
			aux = "";
		}
		PdfPTable table = getDefaultTable();
		table.addCell(getLabelCell(label));
		PdfPCell valueCell = new PdfPCell(new Phrase(aux, normalFont));
		valueCell.setBackgroundColor(backgroundColor);
		valueCell.setBorder(0);
		valueCell.setBorderWidthBottom(2);
		valueCell.setBorderColorBottom(Color.WHITE);
		valueCell.setPaddingBottom(7);
		valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		table.addCell(valueCell);

		document.add(table);
	}

	private void writePairValue(String label, com.lowagie.text.List valueFromDescribedURLList, Document document) throws DocumentException
	{

		PdfPTable table = getDefaultTable();
		table.addCell(getLabelCell(label));
		PdfPCell valueCell = new PdfPCell();
		valueCell.addElement(valueFromDescribedURLList);
		valueCell.setBackgroundColor(backgroundColor);
		valueCell.setBorder(0);
		valueCell.setBorderWidthBottom(2);
		valueCell.setBorderColorBottom(Color.WHITE);
		valueCell.setPaddingBottom(7);
		valueCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		table.addCell(valueCell);

		document.add(table);
	}

	private PdfPTable getDefaultTable()
	{
		float[] widths = { 3, 7 };
		PdfPTable table = new PdfPTable(widths);
		table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
		table.setWidthPercentage(100);
		return table;
	}

	private PdfPTable getOneCellTable()
	{
		PdfPTable table = new PdfPTable(1);
		table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
		table.setWidthPercentage(100);
		return table;
	}

	private String ensureColumn(String value)
	{
		if (value.indexOf(":") < 0)
		{
			return value + " :";
		} else
		{
			return value;
		}
	}

	private PdfPCell getLabelCell(String label)
	{
		String aux = label.trim();
		aux = ensureColumn(aux);
		PdfPCell labelCell = new PdfPCell(new Phrase(aux, normalFont));
		labelCell.setBorder(0);
		labelCell.setBackgroundColor(backgroundColor);
		labelCell.setBorderColorBottom(Color.WHITE);
		labelCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
		labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		labelCell.setBorderWidthBottom(2);
		labelCell.setPaddingBottom(7);
		return labelCell;
	}

	private PdfPCell getTableCell(String label)
	{
		String aux = label;
		if (aux == null)
		{
			aux = "";
		}
		PdfPCell labelCell = new PdfPCell(new Phrase(aux, normalFont));
		labelCell.setBorder(0);
		labelCell.setBackgroundColor(backgroundColor);
		labelCell.setHorizontalAlignment(Element.ALIGN_LEFT);
		labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		labelCell.setPaddingBottom(7);
		return labelCell;
	}

	private PdfPCell getHeaderCell(String label)
	{
		PdfPCell labelCell = new PdfPCell(new Phrase(label.replace(':', ' ').trim(), normalFont));
		labelCell.setBorder(0);
		labelCell.setBackgroundColor(backgroundColor);
		labelCell.setBorderWidthBottom(1);
		labelCell.setBorderColorBottom(Color.BLACK);
		labelCell.setHorizontalAlignment(Element.ALIGN_LEFT);
		labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		labelCell.setPaddingBottom(7);
		return labelCell;
	}

	private PdfPCell getEmptyCell(String message)
	{
		String aux = message;
		if (message == null)
		{
			aux = "";
		}
		PdfPCell labelCell = new PdfPCell(new Phrase(message, normalFont));
		labelCell.setBorder(0);
		labelCell.setBackgroundColor(backgroundColor);
		labelCell.setBorder(0);
		labelCell.setBorderColorBottom(Color.WHITE);
		labelCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
		labelCell.setBorderWidthBottom(2);
		labelCell.setPaddingBottom(7);
		return labelCell;
	}

	private String getLabel(String key)
	{
		return labelProvider.getLabel(key);
	}

	public String getCurrentElement()
	{
		return currentElement;
	}

	public void setCurrentElement(String currentElement)
	{
		if (eventListener != null)
		{
			if (eventListener.isWaitingStart())
			{
				eventListener.setStartName(currentElement);
				eventListener.setWaitingStart(false);
			}
		}
		this.currentElement = currentElement;
	}

	private void closeDocument(Document document)
	{
		if (document.isOpen())
		{
			document.close();
		}
	}

	public String getOutputFileName()
	{
		return outputFileName;
	}

	public void setOutputFileName(String outputFileName)
	{
		this.outputFileName = outputFileName;
	}

	private boolean isEmpty(List<? extends Object> list)
	{
		if ((list == null) || (list.size() == 0))
		{
			return true;
		}
		return false;
	}

}
